#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#include "dxManager.h"
#include "camera.h"
#include "Main.h"

/*******************************************************************
* Global Variables
*******************************************************************/
HWND hWnd;					//window handle
int windowWidth = 800;	
int windowHeight = 600;
Camera *camera;
//directX manager
dxManager dx;
bool texturesEnabled = true;
bool fullscreen = true;

/*******************************************************************
* Main Window Procedure - handles application events
*******************************************************************/
LPCWSTR renderingTech;
wchar_t buff[255];
char* renderingText = "Last Action: Switch Rendering to %s\0";
LRESULT CALLBACK wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
		// Allow the user to press the escape key to end the application
	case WM_KEYDOWN	:
		if(wParam == VK_ESCAPE)
			PostQuitMessage(0);
		else if (wParam == 0x56)
		{
			if (fullscreen)
			{
				windowHeight = windowWidth * GetSystemMetrics(SM_CYSCREEN) / GetSystemMetrics(SM_CXSCREEN);
				SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX); 
				SetWindowPos(hWnd, HWND_TOP, 100, 100, windowWidth, windowHeight, SWP_FRAMECHANGED | SWP_SHOWWINDOW); 
				fullscreen = false;
				dx.setInfoText(TEXT("Press <V> for fullscreen mode"));
			}
			else
			{
				int width = GetSystemMetrics(SM_CXSCREEN);
				int height = GetSystemMetrics(SM_CYSCREEN);
				SetWindowLongPtr(hWnd, GWL_STYLE, WS_EX_TOPMOST | WS_POPUP); 
				SetWindowPos(hWnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW); 
				fullscreen = true;
				dx.setInfoText(TEXT("Press <V> for window mode"));
			}
		}
		else
			switch(wParam)
			{
				case 0x41: //a
						camera->moveLeftOn();
						dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case 0x44://d
						camera->moveRightOn();
						dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case 0x48://h
						dx.setInfoText(TEXT("Helptext:\n\tCameramovement\n\t\tWASD : Move around\n\t\tArrow Keys : Pitch&Roll\n\tShadingtechniques\n\t\t Numpad 0 : Swap Textures\n\t\t Numpad 1 : Switch Renderingtech\n\t\t V : view mode (window/fullscreen)"));
					break;
				case 0x57://w
						camera->moveForwardOn();
						dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case 0x53://s
						camera->moveBackwardOn();
						dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case VK_UP :
					camera->pitchUpOn();
					dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case VK_DOWN :
					camera->pitchDownOn();
					dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case VK_LEFT:
					camera->pitchLeftOn();
					dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case VK_RIGHT:
					camera->pitchRightOn();
					dx.setInfoText(TEXT("Last Action: Moving"));
					break;
				case VK_NUMPAD1 :
					renderingTech = dx.switchRenderingTech();
					swprintf(buff,wcslen(renderingTech) + 3 + strlen(renderingText),TEXT("Last Action: Switch Renderingtech to %s\0"),renderingTech);
					dx.setInfoText(buff);
					break;
				case VK_NUMPAD0 :
						dx.swapTexture();
						dx.setInfoText(TEXT("Last Action: Switched Textures"));
					break;
		}
        break;		
	case WM_KEYUP :
		switch(wParam)
		{
			case 0x41:
				camera->moveLeftOff();
				break;
			case 0x44:
				camera->moveRightOff();
				break;
			case 0x57:
				camera->moveForwardOff();
				break;
			case 0x53:
				camera->moveBackwardOff();
				break;
			case VK_UP :
				camera->pitchUpOff();
				break;
			case VK_DOWN :
				camera->pitchDownOff();
				break;
			case VK_LEFT:
				camera->pitchLeftOff();
				break;
			case VK_RIGHT:
				camera->pitchRightOff();
				break;
		}
		break;
		case WM_DESTROY	:	PostQuitMessage(0);
		break;
	}
	
	return DefWindowProc(hWnd, message, wParam, lParam);
}

/*******************************************************************
* Initialize Main Window
********************************************************************/
bool initWindow(HWND &hWnd, HINSTANCE hInstance, int width, int height)
{
	WNDCLASSEX wcex;

	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)wndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= 0;
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= TEXT("DXWindow");
	wcex.hIconSm		= 0;
	RegisterClassEx(&wcex);

	//create the window from the class above
	//disable resizing and correct for extra width and height
	hWnd = CreateWindow( L"DXWindow", 
						 L"Rene Boeing, Silvio Kuehn, Marc Wilmes", 
					     WS_EX_TOPMOST | WS_POPUP, // WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
						 0, // CW_USEDEFAULT
						 0, // CW_USEDEFAULT					
						 width, 
						 height, 
						 NULL, 
						 NULL, 
						 hInstance, 
						 NULL);
   
	//window handle not created
	if (!hWnd) return false;
	
	//if window creation was successful
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);
	return true;
}

/*******************************************************************
* WinMain
*******************************************************************/
int APIENTRY _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
	// get screen size and set up the application window
	int width = GetSystemMetrics(SM_CXSCREEN);
	int height = GetSystemMetrics(SM_CYSCREEN);
	if ( !initWindow(hWnd, hInstance, width, height)) return -1;
	
	//set up directx manager
	if ( !dx.initialize(&hWnd) ) return -2;
	camera = dx.getCamera();
	dx.setInfoText(TEXT("Liste der vorhanden Befehle auf 'h'"));
	// Main message loop
    MSG msg = {0};
    while (WM_QUIT != msg.message)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);			
		}	
		camera->update();
		dx.renderScene();
    }

	return (int) msg.wParam;
}